package com.mazaiting;

import com.mazaiting.classfile.attr.MemberInfo;
import com.mazaiting.classfile.attr.info.CodeAttribute;
import com.mazaiting.instructions.InstructionFactory;
import com.mazaiting.instructions.base.BytecodeReader;
import com.mazaiting.instructions.base.Instruction;
import com.mazaiting.rtda.MtFrame;
import com.mazaiting.rtda.MtThread;
import com.mazaiting.rtda.heap.MtMethod;
import lombok.extern.slf4j.Slf4j;

/**
 * 解释器
 *
 * @author mazaiting
 * @since 2021/8/15
 */
@Slf4j
public class Interpreter {

    /**
     * 解释器
     * @param method 方法信息
     */
    public static void interpret(MtMethod method) {
        try {
            // 创建线程实例
            MtThread thread = new MtThread();
            MtFrame frame = thread.newFrame(method);
            thread.pushFrame(frame);
            loop(thread, method.getCode());
        } catch (Exception e) {
            log.error("执行异常: {}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 循环执行
     * @param thread 当前线程
     * @param code 二进制代码
     */
    private static void loop(MtThread thread, byte[] code) {
        // 取出顶部栈帧
        MtFrame frame = thread.popFrame();
        BytecodeReader reader = new BytecodeReader();
        while (true) {
            // 获取下一个计数器
            int pc = frame.getNextPc();
            thread.setPc(pc);
            // 解码
            reader.reset(code, pc);
            // 操作码
            short opCode = reader.readU1ToUnsignedByte();
            try {
                // 获取指令
                Instruction instruction = InstructionFactory.newInstruction(opCode);
                // 加载操作数
                instruction.fetchOperands(reader);
                // 设置下一步
                frame.setNextPc(reader.getPc());
                // 执行
                log.debug("pc:{} inst:{} ", pc, instruction);
                instruction.execute(frame);
            } catch (Exception e) {
                // 此处捕获异常是为了查看本地变量表中的内容
                log.debug("异常");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
                //throw new RuntimeException(e);
            }

        }
    }
}













